Repository navigation
Conversation
…ng an item
Each item of `exec::iterate` is `sequence(schedule(trampoline), item)`,
and the trampoline's schedule sender completes with `set_stopped` when
stop has been requested. That happens before the item reads `*it++`, so
a stopped item leaves the iterator where it was. `iterate` relied on the
next sender to pass the `set_stopped` back, and ended the sequence only
then. A next sender is free to complete with `set_value` after a stopped
item, as the ones in `test_iterate.cpp` and `test_merge_each.cpp` do,
and then `iterate` emitted the same element again, which was stopped
again, and so on without end. For example, this never completes once
`stop_source.request_stop()` has been called:
iterate(std::views::iota(0, 100))
| transform_each(upon_stopped([] {}))
| ignore_all_values()
| write_env(prop{get_stop_token, stop_source.get_token()})
This diff checks the receiver's stop token before emitting the next
item, and completes the sequence with `set_stopped` if stop has been
requested and elements remain. A sequence whose last item requests stop
still completes with `set_value`, as before.
The new test uses a receiver whose next senders ignore `set_stopped`,
and requests stop from an item, before the start, and from the last
item.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2446
Each item of
exec::iterateissequence(schedule(trampoline), item). Once stop has been requested, the trampoline's schedule sender completes withset_stoppedbefore the item reads*it++, so a stopped item leaves the iterator where it was.iterateended the sequence only when the next sender passed thatset_stoppedback. A next sender that completes withset_valueafter a stopped item made__start_next()emit the same element again, without end (the reproducer in #2446 gives up after one million stopped items).This change checks the receiver's stop token in
__start_next()before emitting the next item. If stop has been requested and elements remain, the sequence completes withset_stopped(through__set_value_unless_stopped, as__next_receiver::set_stoppeddoes). A sequence whose last item requests stop still completes withset_value. For receivers with an unstoppable token the check is a constantfalse.#2446 left open whether this is a bug in
iterateor whether next senders are required to passset_stoppedback after a stopped item; there has been no reply on that yet. This PR takes the first reading, which matches the receivers intest_iterate.cppandtest_merge_each.cppthat answerset_valueafter a stopped item. If next senders are required to propagateset_stopped, this is a hardening change only, and it can be closed in favour of documenting that rule.Tests
Added to
test/exec/sequence/test_iterate.cpp:iterate - stops when stop is requested, even if the next senders ignore it, with a receiver whose next senders complete withset_valueafter a stopped item. It gives up after 100 items, so the test fails on main instead of hanging. Sections: stop requested by an item, before the start, and by the last item (the last one passes on main too).Run on x86_64 Linux, Debug, C++20, at
f71dc7d0:test.exec "iterate*"on main + new testtest.execwith the fix101 == 3,101 == 0)The branch is now rebased onto
8b2019b5; neither changed file was touched upstream in between, and the tests were not re-run after the rebase. clang-format 21.1.8 (--dry-run --Werror) reports no violations on the two changed files. libc++, gcc 12/14/15, MSVC,-fno-exceptions, the sanitizer rows and the modules build were not run locally.This change was drafted with Claude Code (claude-opus-5-5); the test results above are from the runs described.